package com.tenthoundsqps.service.sync;

import com.tenthoundsqps.entity.Order;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单数据同步服务
 * 负责将订单数据从数据库同步到Elasticsearch（因为后面查询会根据es索引查询订单Id,然后通过多级缓存查询订单详情，所以在订单创建的时候需要将订单数据存进es中）
 * 储存的方式有以下3种：
 *
 * 同步策略：
 * 1. 应用层同步：在订单创建/更新时直接同步到ES
 * 2. 异步同步：通过消息队列实现异步数据同步
 * 3. 批量同步：定时任务批量同步数据
 */
@Service
public class OrderSyncService {
    
    private static final Logger logger = LoggerFactory.getLogger(OrderSyncService.class);
    
    /**
     * Elasticsearch高级客户端
     * 用于执行索引和删除操作
     * 
     * 注意：RestHighLevelClient 在 Elasticsearch 7.15+ 中已被弃用，
     * 但在当前版本中仍可使用。建议在升级到 Elasticsearch 8.0+ 时
     * 迁移到新的 Java API Client。
     */
    @Autowired
    private RestHighLevelClient elasticsearchClient;
    
    // Elasticsearch索引名称
    private static final String ORDER_INDEX = "orders";
    
    // 日期时间格式化器
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    
    /**
     * 初始化方法
     * 可用于初始化同步服务相关配置
     */
    @PostConstruct
    public void init() {
        logger.info("OrderSyncService initialized");
    }
    
    /**
     * 同步订单到Elasticsearch（应用层同步）
     * 在订单创建或更新时直接调用此方法同步数据
     * 
     * @param order 订单对象
     */
    public void syncOrderToElasticsearch(Order order) {
        try {
            // 构造要同步到ES的文档数据
            Map<String, Object> document = buildOrderDocument(order);
            
            // 创建索引请求
            IndexRequest indexRequest = new IndexRequest(ORDER_INDEX);
            indexRequest.id(String.valueOf(order.getId())); // 使用订单ID作为文档ID
            indexRequest.source(document); // 移除XContentType参数
            
            // 执行索引操作
            elasticsearchClient.index(indexRequest, RequestOptions.DEFAULT);
            
            logger.info("Order synced to Elasticsearch, orderId: {}", order.getId());
        } catch (IOException e) {
            logger.error("Failed to sync order to Elasticsearch, orderId: {}", order.getId(), e);
        }
    }
    
    /**
     * 从Elasticsearch中删除订单（应用层同步）
     * 在订单被删除时调用此方法
     * 
     * @param orderId 订单ID
     */
    public void deleteOrderFromElasticsearch(Long orderId) {
        try {
            // 创建删除请求
            DeleteRequest deleteRequest = new DeleteRequest(ORDER_INDEX, String.valueOf(orderId));
            
            // 执行删除操作
            elasticsearchClient.delete(deleteRequest, RequestOptions.DEFAULT);
            
            logger.info("Order deleted from Elasticsearch, orderId: {}", orderId);
        } catch (IOException e) {
            logger.error("Failed to delete order from Elasticsearch, orderId: {}", orderId, e);
        }
    }
    
    /**
     * 构造订单文档数据
     * 将Order实体对象转换为Elasticsearch文档格式
     * 
     * @param order 订单对象
     * @return 文档数据Map
     */
    private Map<String, Object> buildOrderDocument(Order order) {
        Map<String, Object> document = new HashMap<>();
        
        // 映射数据库字段到Elasticsearch文档字段
        document.put("orderNo", order.getOrderNo());           // 订单编号
        document.put("userId", order.getUserId());             // 用户ID
        document.put("merchantId", order.getMerchantId());     // 商户ID
        document.put("merchantName", order.getMerchantName()); // 商户名称
        document.put("phoneNumber", order.getPhoneNumber());   // 联系电话
        document.put("amount", order.getAmount());             // 订单金额
        document.put("status", order.getStatus());             // 订单状态
        document.put("archived", order.getArchived());         // 归档状态
        
        // 时间字段需要特殊处理
        if (order.getCreateTime() != null) {
            document.put("createTime", order.getCreateTime().format(DATE_TIME_FORMATTER));
        }
        
        if (order.getUpdateTime() != null) {
            document.put("updateTime", order.getUpdateTime().format(DATE_TIME_FORMATTER));
        }
        
        return document;
    }
    
    /**
     * 批量同步订单到Elasticsearch
     * 用于定时任务批量同步数据
     * 
     * @param orders 订单列表
     */
    public void bulkSyncOrdersToElasticsearch(List<Order> orders) {
        logger.info("Starting bulk sync orders to Elasticsearch, order count: {}", orders.size());
        
        int successCount = 0;
        for (Order order : orders) {
            try {
                syncOrderToElasticsearch(order);
                successCount++;
            } catch (Exception e) {
                logger.error("Failed to sync order to Elasticsearch, orderId: {}", order.getId(), e);
            }
        }
        
        logger.info("Bulk sync completed, success: {}, total: {}", successCount, orders.size());
    }
}